/*!
 * \file t3_ejb.c
 *
 * \brief t3数据包解析
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 *
 * \version 2.0
 * \author wuwk
 * \date 2016/1/11
 *
 */
#include <stdio.h>
#include <string.h>
#include <iconv2utf8.h>

#include "frcomm.h"
#include "wls_parse_message.h"
#include "t3_core.h"
#include "t3_ejb.h"

#define WEBLOGIC_EJB_METHODDESC          "weblogic.rmi.internal.MethodDescriptor"
#define WEBLOGIC_EJB_CLASSTABLEENTRY     "weblogic.rjvm.ClassTableEntry"

#define JAVA_LANG_STRING_DOT             "java.lang.String;"
#define JAVA_LANG_STRING_SLASH           "java/lang/String;"

#define T3_EJB_FUNC                      "request.ejb.function"
#define T3_EJB_FUNC_ARG                  "request.ejb.function.arg"

#define T3_EJB_FUNC_RETURN               "response.ejb.function"

/*!
 * t3 取;前字符串
 *
 * \param *p_data           (char  数据)
 * \param *i_len            (返回长度)
 *
 */
FR_STATIC void __t3_ejb_getstring_bysemicolon(char *p_data, int *i_len)
{
    char *p_semicolon = NULL;

    *i_len = 0;
    if (p_data == NULL || *p_data == ';')
        return;

    p_semicolon = strchr(p_data, ';');
    if (p_semicolon == NULL)
        return;

    *i_len = p_semicolon - p_data;
    return;
}

/*!
 * t3 bytebuff复制
 *
 * \param *p_st_data        (Frbyte_Packet  bytebuff数据)
 *
 * \return p_st_new:成功\n
 *         NULL:失败\n
 *
 */
FR_STATIC Frbyte_Packet *__t3_ejb_bytebuff_copy(Frbyte_Packet *p_st_data)
{
    Frbyte_Packet *p_st_new = NULL;
    char *p_data = NULL;
    uint32_t u32_len = 0;

    if (p_st_data == NULL || bytebuff_remaining(p_st_data) == 0)
        return NULL;

    u32_len = bytebuff_remaining(p_st_data);

    p_data = (char *)frmalloc(u32_len + 1);
    if (p_data == NULL)
        return NULL;
    memset(p_data, 0x00, u32_len + 1);

    if (bytebuff_get_bytes(p_st_data, p_data, u32_len) == FR_FAIL)
    {
        frfree(p_data);
        return NULL;
    }

    p_st_new = bytebuff_creat();
    if (p_st_new == NULL)
    {
        frfree(p_data);
        return NULL;
    }

    if (bytebuff_add(p_st_new, p_data, u32_len) == FR_FAIL)
    {
        frfree(p_data);
        bytebuff_free(&p_st_new);
        return NULL;
    }
    frfree(p_data);

    return p_st_new;
}

/*!
 * t3 取class个数
 *
 * \param *p_st_data           (Frbyte_Packet          数据)
 *
 * \return class个数:成功\n
 *         0:失败\n
 *
 */
FR_STATIC int __t3_get_class_count(Frbyte_Packet *p_st_data)
{
    uint8_t u8_char = 0;
    int i_idx = 0;

    if (p_st_data == NULL)
        return 0;

    if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, "\x78\x70\x77", 3, &i_idx) == FR_FAIL)
        return 0;

    bytebuff_setPosition(p_st_data, i_idx+3);

    if (bytebuff_get_char(p_st_data, &u8_char) == FR_FAIL)
        return 0;

    return (int)u8_char;
}

/*!
 * t3 class解析
 *
 * \param *p_st_arg            (Frbyte_Packet          参数数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
FR_STATIC int __t3_ejb_class_analysis(Frbyte_Packet *p_st_arg, Frbyte_Packet *p_st_data)
{
    char *p_mem_type = NULL;
    char arr_tmp[3];
    uint16_t u16_value = 0;
    uint8_t u8_char = 0;
    int i_idx = 0;

    if (p_st_arg == NULL || p_st_data == NULL)
        return FR_FAIL;

    //跳过参数名
    if (wls_skip_utf(p_st_arg) == FR_FAIL)
        return FR_FAIL;

    if (bytebuff_peek_char(p_st_arg, &u8_char) == FR_FAIL)
        return FR_FAIL;

    if (u8_char == 't')
    {
        bytebuff_skip(p_st_arg, 1);
        if (bytebuff_get_short(p_st_arg, 2, &u16_value, BYTE_BIG_ENDIAN) == FR_FAIL)
            return FR_FAIL;

        p_mem_type = (char *)frmalloc(u16_value + 1);
        if (p_mem_type == NULL)
            return FR_FAIL;
        memset(p_mem_type, 0x00, u16_value + 1);
        if (bytebuff_get_bytes(p_st_arg, p_mem_type, u16_value) == FR_FAIL)
            goto err;

        if (*p_mem_type == 'L'
            && (strncmp(p_mem_type+1, JAVA_LANG_STRING_SLASH, strlen(JAVA_LANG_STRING_SLASH)) != 0))
        {
            // class开始
            if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, "\x73\x72", 2, &i_idx) == FR_FAIL)
                goto err;

            bytebuff_setPosition(p_st_data, i_idx+5);
            // class结束
            if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, "\x70", 1, &i_idx) == FR_FAIL)
                goto err;
            bytebuff_setPosition(p_st_data, i_idx+1);
        }
        else
        {
            memset(arr_tmp, 0x00, sizeof(arr_tmp));
            if (bytebuff_peek_bytes(p_st_data, arr_tmp, 2) == FR_FAIL)
                goto err;

            if (arr_tmp[0] != '\x70')
            {
                if (wls_skip_utf(p_st_data) == FR_FAIL)
                    goto err;
            }
        }
        frfree(p_mem_type);
        p_mem_type = NULL;
    }
    else
    {
        memset(arr_tmp, 0x00, sizeof(arr_tmp));
        if (bytebuff_peek_bytes(p_st_data, arr_tmp, 2) == FR_FAIL)
            goto err;

        if (arr_tmp[0] != '\x70')
        {
            if (wls_skip_utf(p_st_data) == FR_FAIL)
                goto err;
        }
    }

    return FR_SUCC;

err:
    if (p_mem_type)
        frfree(p_mem_type);
    return FR_FAIL;
}

/*!
 * t3 参数为class时解析
 *
 * \param *p_st_data           (Frbyte_Packet  数据)
 * \param *p_class_start       (char           类开头地址)
 * \param i_class_len          (int            类长度)
 * \param *p_key               (char           上报key)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
FR_STATIC int __t3_ejb_arg_class(Frbyte_Packet *p_st_data
                               , Frreport_body_data *p_st_body_data
                               , char *p_class_start
                               , int i_class_len
                               , char *p_key)
{
    Frbyte_Packet *p_st_arg = NULL;
    char *p_arg_data = NULL;
    char *p_class = NULL;
    char *p_mem_type = NULL;
    uint16_t u16_count = 0;
    uint16_t u16_value = 0;
    uint32_t u32_value = 0;
    uint64_t u64_value = 0;
    uint8_t u8_char = 0;
    int i_pos = 0;
    int i_copy_len = 0;
    int i_idx = 0;
    int i = 0;

    if (p_st_data == NULL || p_class_start == NULL)
        return FR_FAIL;

    p_class = (char *)frmalloc(i_class_len + 1);
    if (p_class == NULL)
        return FR_FAIL;
    snprintf(p_class, i_class_len + 1, "%s", p_class_start);

    //上报class名
    if (frreport_body_l7_add_str(p_st_body_data, p_key, p_class) == FR_FAIL)
        goto err;

    i_pos = bytebuff_getPosition(p_st_data);

    //找到参数说明
    if (bytebuff_memstr(p_st_data, i_pos, 0, p_class, i_class_len, &i_idx) == FR_FAIL)
        goto err;

    bytebuff_setPosition(p_st_data, i_idx+i_class_len);
    bytebuff_skip(p_st_data, 9);

    i_copy_len = bytebuff_remaining(p_st_data);
    p_arg_data = (char *)frmalloc(i_copy_len + 1);
    if (p_arg_data == NULL)
        goto err;
    memset(p_arg_data, 0x00, i_copy_len + 1);

    if (bytebuff_get_bytes(p_st_data, p_arg_data, i_copy_len) == FR_FAIL)
        goto err;

    //复制参数说明部分
    p_st_arg = bytebuff_creat();
    if (p_st_arg == NULL)
        goto err;

    if (bytebuff_add(p_st_arg, p_arg_data, i_copy_len) == FR_FAIL)
        goto err;

    bytebuff_setPosition(p_st_data, i_pos);

    // 参数个数
    if (bytebuff_get_short(p_st_arg, 2, &u16_count, BYTE_BIG_ENDIAN) == FR_FAIL)
        goto err;

    bytebuff_skip(p_st_data, 5);
    for (; i < u16_count; i++)
    {
        if (bytebuff_get_char(p_st_arg, &u8_char) == FR_FAIL)
            return FR_FAIL;

        switch (u8_char)
        {
            case 'S':
            case 'C':
                if (bytebuff_get_short(p_st_data, 2, &u16_value, BYTE_BIG_ENDIAN) == FR_FAIL)
                    goto err;
                //跳过参数名
                if (wls_skip_utf(p_st_arg) == FR_FAIL)
                    goto err;
                break;
            case 'I':
            case 'F':
                if (bytebuff_get_int(p_st_data, 4, &u32_value, BYTE_BIG_ENDIAN) == FR_FAIL)
                    goto err;
                //跳过参数名
                if (wls_skip_utf(p_st_arg) == FR_FAIL)
                    goto err;
                break;
            case 'D':
            case 'J':
                if (bytebuff_get_long(p_st_data, 8, &u64_value, BYTE_BIG_ENDIAN) == FR_FAIL)
                    goto err;
                //跳过参数名
                if (wls_skip_utf(p_st_arg) == FR_FAIL)
                    goto err;
                break;
            case 'Z':
            case 'B':
                if (bytebuff_get_char(p_st_data, &u8_char) == FR_FAIL)
                    goto err;
                //跳过参数名
                if (wls_skip_utf(p_st_arg) == FR_FAIL)
                    goto err;
                break;
            case '[':
            case 'L':
                if ( __t3_ejb_class_analysis(p_st_arg, p_st_data) == FR_FAIL)
                    goto err;
                break;
            default:
                break;
        }
    }

    frfree(p_class);
    frfree(p_arg_data);
    bytebuff_free(&p_st_arg);

    return FR_SUCC;

err:
    frfree(p_class);
    if (p_arg_data)
        frfree(p_arg_data);
    if (p_st_arg)
        bytebuff_free(&p_st_arg);
    if (p_mem_type)
        frfree(p_mem_type);

    return FR_FAIL;
}

/*!
 * t3 ejb解析
 *
 * \param *p_st_session        (L7session_t3_private  t3 session数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
FR_STATIC int __t3_ejb_getname(Frbyte_Packet *p_st_data, L7Session_t3 *p_st_session)
{
    char *p_ejbname = NULL;
    uint16_t u16_len = 0;
    int i_idx = 0;
    int i_ret = 0;

    if (p_st_session == NULL || p_st_data == NULL)
        return FR_FAIL;

    if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, WEBLOGIC_EJB_BUSINESSOBJ, strlen(WEBLOGIC_EJB_BUSINESSOBJ), &i_idx) == FR_FAIL)
        return FR_FAIL;
    bytebuff_setPosition(p_st_data, i_idx+strlen(WEBLOGIC_EJB_BUSINESSOBJ));

    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    p_ejbname = (char *)frmalloc(u16_len + 1);
    if (p_ejbname == NULL)
        return FR_FAIL;
    memset(p_ejbname, 0x00, u16_len + 1);

    i_ret = bytebuff_get_bytes(p_st_data, p_ejbname, u16_len);
    if (i_ret == FR_FAIL)
    {
        frfree(p_ejbname);
        return FR_FAIL;
    }
    p_ejbname[u16_len-1] = '\0';

    if (p_st_session->p_ejbname)
        frfree(p_st_session->p_ejbname);
    p_st_session->p_ejbname = p_ejbname;

    if (p_st_session->p_title)
        frfree(p_st_session->p_title);

    p_st_session->p_title = frstrdup(p_st_session->p_ejbname);
    if (p_st_session->p_title == NULL)
        return FR_FAIL;

    return FR_SUCC;
}

/*!
 * t3 ejb 方法的参数解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param *p_arg_str           (int                   参数说明的字符串)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
FR_STATIC int __t3_ejb_getarg(L7session_t3_private *p_st_private
                            , Frbyte_Packet *p_st_data
                            , Frreport_body_data *p_st_body_data
                            , char *p_arg_str)
{
    char *p_arg_str_tmp = NULL;
    char *p_data = NULL;
    char *p_iconved_buf = NULL;
    char arr_key[64];
    char arr_tmp[2];
    char arr_char[3];
    uint8_t u8_char = 0;
    uint16_t u16_short = 0;
    uint16_t u16_len = 0;
    uint32_t u32_int = 0;
    uint32_t u32_len = 0;
    uint64_t u64_long = 0;
    union int32_float_bits u_32bits;
    union int64_double_bits u_64bits;
    float f_value = 0.0;
    double db_value = 0.0;
    unsigned int ui_iconved_len = 0;
    int i_len_semicolon = 0;
    int i_len = 0;
    int i_arg_count = 0;
    int i_ret = 0;

    if (p_st_private == NULL || p_st_data == NULL || p_st_body_data == NULL
        || p_arg_str == NULL)
        return FR_FAIL;

    p_arg_str_tmp = p_arg_str;
    for (; *p_arg_str_tmp != '\0'; p_arg_str_tmp++, i_arg_count++)
    {
        switch (*p_arg_str_tmp)
        {
            case 'S': //short
                if (bytebuff_get_short(p_st_data, 2, &u16_short, BYTE_BIG_ENDIAN) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d", T3_EJB_FUNC_ARG, i_arg_count+1);

                if (frreport_body_l7_add_int(p_st_body_data, arr_key, u16_short)== FR_FAIL)
                    return FR_FAIL;
                break;
            case 'I': //int
                if (bytebuff_get_int(p_st_data, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d", T3_EJB_FUNC_ARG, i_arg_count+1);

                if (frreport_body_l7_add_int(p_st_body_data, arr_key, u32_int)== FR_FAIL)
                    return FR_FAIL;
                break;
            case 'J': //long
                if (bytebuff_get_long(p_st_data, 8, &u64_long, BYTE_BIG_ENDIAN) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d", T3_EJB_FUNC_ARG, i_arg_count+1);

                if (frreport_body_l7_add_long(p_st_body_data, arr_key, u64_long)== FR_FAIL)
                    return FR_FAIL;
                break;
            case 'F': //float
                if (bytebuff_get_int(p_st_data, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d", T3_EJB_FUNC_ARG, i_arg_count+1);

                u_32bits.int_bits = u32_int;
                f_value = u_32bits.float_bits;

                if (frreport_body_l7_add_float(p_st_body_data, arr_key, f_value) == FR_FAIL)
                    return FR_FAIL;
                break;
            case 'D': //double
                if (bytebuff_get_long(p_st_data, 8, &u64_long, BYTE_BIG_ENDIAN) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d", T3_EJB_FUNC_ARG, i_arg_count+1);

                u_64bits.int_bits = u64_long;
                db_value = u_64bits.double_bits;

                if (frreport_body_l7_add_double(p_st_body_data, arr_key, db_value) == FR_FAIL)
                    return FR_FAIL;
                break;
            case 'C': //char
                memset(arr_char, 0x00, sizeof(arr_char));
                if (bytebuff_get_bytes(p_st_data, arr_char, 2) == FR_FAIL)
                    return FR_FAIL;

                i_ret = iconv_to_utf8(arr_char, 2, (char *)"UNICODEBIG", &p_iconved_buf, &ui_iconved_len);
                if (i_ret != 0)
                {
                    if (p_iconved_buf)
                        frfree(p_iconved_buf);
                }

                snprintf(arr_key, sizeof(arr_key), "%s.%d", T3_EJB_FUNC_ARG, i_arg_count+1);

                snprintf(arr_tmp, sizeof(arr_tmp), "%s", p_iconved_buf);
                frfree(p_iconved_buf);

                if (frreport_body_l7_add_str(p_st_body_data, arr_key, arr_tmp) == FR_FAIL)
                    return FR_FAIL;
                break;
            case '[': //bytes
                p_arg_str_tmp++;
                if (*p_arg_str_tmp != 'B')
                    return FR_FAIL;

                if (bytebuff_peek_char(p_st_data, &u8_char) == FR_FAIL)
                    return FR_FAIL;

                if (u8_char == '\x75')
                {
                    bytebuff_skip(p_st_data, 5);

                    if (bytebuff_get_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
                        return FR_FAIL;

                    snprintf(arr_key, sizeof(arr_key), "%s.%d", T3_EJB_FUNC_ARG, i_arg_count+1);

                    p_data = (char *)frmalloc(u32_len);
                    if(p_data == NULL)
                        return FR_FAIL;

                    if(bytebuff_get_bytes(p_st_data, p_data, u32_len) == FR_FAIL)
                    {
                        frfree(p_data);
                        return FR_FAIL;
                    }

                    if (frreport_body_l7_add_bin(p_st_body_data, arr_key, p_data, u32_len) == FR_FAIL)
                    {
                        frfree(p_data);
                        return FR_FAIL;
                    }
                    frfree(p_data);
                }
                else
                {
                    snprintf(arr_key, sizeof(arr_key), "%s.%d", T3_EJB_FUNC_ARG, i_arg_count+1);
                    if (frreport_body_l7_add_bin(p_st_body_data, arr_key, NULL, 0) == FR_FAIL)
                        return FR_FAIL;
                }
                break;
            case 'L': //string
                p_arg_str_tmp++;

                //取到;为止
                __t3_ejb_getstring_bysemicolon(p_arg_str_tmp, &i_len_semicolon);
                if (i_len_semicolon == 0)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d", T3_EJB_FUNC_ARG, i_arg_count+1);
                //string类型
                i_len = strlen(JAVA_LANG_STRING_DOT);
                if (i_len_semicolon == (i_len-1)
                    && strncmp(p_arg_str_tmp, JAVA_LANG_STRING_DOT, i_len_semicolon) == 0)
                {
                    p_arg_str_tmp += i_len_semicolon;

                    if (bytebuff_peek_char(p_st_data, &u8_char) == FR_FAIL)
                        return FR_FAIL;
                    // String
                    if (u8_char == '\x74')
                    {
                        bytebuff_skip(p_st_data, 1);
                        if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
                            return FR_FAIL;

                        p_data = (char *)frmalloc(u16_len + 1);
                        if (p_data == NULL)
                            return FR_FAIL;
                        memset(p_data, 0x00, u16_len + 1);

                        if (bytebuff_get_bytes(p_st_data, p_data, u16_len) == FR_FAIL)
                        {
                            frfree(p_data);
                            return FR_FAIL;
                        }

                        if (frreport_body_l7_add_str(p_st_body_data, arr_key, p_data) == FR_FAIL)
                        {
                            frfree(p_data);
                            return FR_FAIL;
                        }
                        frfree(p_data);
                    }
                    else
                    {
                        if (frreport_body_l7_add_str(p_st_body_data, arr_key, p_data) == FR_FAIL)
                            return FR_FAIL;
                    }
                }
                else //class类型
                {
                    i_ret = __t3_ejb_arg_class(p_st_data, p_st_body_data, p_arg_str_tmp, i_len_semicolon, arr_key);
                    if (i_ret == FR_FAIL)
                        return FR_FAIL;
                    p_arg_str_tmp += i_len_semicolon;
                }
                break;
            case 'Z': //boolean
                if (bytebuff_get_char(p_st_data, &u8_char) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d", T3_EJB_FUNC_ARG, i_arg_count+1);

                if (frreport_body_l7_add_int(p_st_body_data, arr_key, u8_char) == FR_FAIL)
                    return FR_FAIL;
                break;
            case 'B': //byte
                if (bytebuff_get_char(p_st_data, &u8_char) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d", T3_EJB_FUNC_ARG, i_arg_count+1);

                if (frreport_body_l7_add_int(p_st_body_data, arr_key, u8_char) == FR_FAIL)
                    return FR_FAIL;
                break;
            default:
                return FR_FAIL;
        }
    }

    return FR_SUCC;
}

/*!
 * t3 ejb 返回内容结构体解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param *p_arg_str           (int                   参数说明的字符串)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
FR_STATIC int __t3_ejb_get_funcvalue(Frbyte_Packet *p_st_data
                                   , Frbyte_Packet *p_st_member
                                   , Frreport_body_data *p_st_body_data
                                   , uint16_t u16_count
                                   , uint32_t u32_count)
{
    char arr_key[64];
    char arr_tmp[2];
    char arr_char[3];
    char *p_data = NULL;
    char *p_iconved_buf = NULL;
    union int32_float_bits u_32bits;
    union int64_double_bits u_64bits;
    float f_value = 0.0;
    double db_value = 0.0;
    uint8_t u8_char = 0;
    uint16_t u16_short = 0;
    uint16_t u16_len = 0;
    uint32_t u32_int = 0;
    uint64_t u64_long = 0;
    unsigned int ui_iconved_len = 0;
    int i = 0;
    int i_ret = 0;

    if (p_st_data == NULL || p_st_member == NULL || p_st_body_data == NULL)
        return FR_FAIL;

    for (; i < u16_count; i++)
    {
        if (bytebuff_get_char(p_st_member, &u8_char) == FR_FAIL)
            return FR_FAIL;

        switch (u8_char)
        {
            case 'S': //short
                if (bytebuff_get_short(p_st_data, 2, &u16_short, BYTE_BIG_ENDIAN) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d.%d", T3_EJB_FUNC_RETURN, u32_count, i+1);
                if (frreport_body_l7_add_int(p_st_body_data, arr_key, u16_short)== FR_FAIL)
                    return FR_FAIL;

                // 跳过成员名
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;
                break;
            case 'I': //int
                if (bytebuff_get_int(p_st_data, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d.%d", T3_EJB_FUNC_RETURN, u32_count, i+1);
                if (frreport_body_l7_add_int(p_st_body_data, arr_key, u32_int)== FR_FAIL)
                    return FR_FAIL;

                // 跳过成员名
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;
                break;
            case 'J': //long
                if (bytebuff_get_long(p_st_data, 8, &u64_long, BYTE_BIG_ENDIAN) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d.%d", T3_EJB_FUNC_RETURN, u32_count, i+1);
                if (frreport_body_l7_add_long(p_st_body_data, arr_key, u64_long)== FR_FAIL)
                    return FR_FAIL;

                // 跳过成员名
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;

                break;
            case 'F': //float
                if (bytebuff_get_int(p_st_data, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d.%d", T3_EJB_FUNC_RETURN, u32_count, i+1);

                u_32bits.int_bits = u32_int;
                f_value = u_32bits.float_bits;

                if (frreport_body_l7_add_float(p_st_body_data, arr_key, f_value) == FR_FAIL)
                    return FR_FAIL;

                // 跳过成员名
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;

                break;
            case 'D': //double
                if (bytebuff_get_long(p_st_data, 8, &u64_long, BYTE_BIG_ENDIAN) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d.%d", T3_EJB_FUNC_RETURN, u32_count, i+1);

                u_64bits.int_bits = u64_long;
                db_value = u_64bits.double_bits;

                if (frreport_body_l7_add_double(p_st_body_data, arr_key, db_value) == FR_FAIL)
                    return FR_FAIL;

                // 跳过成员名
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;

                break;
            case 'C': //char
                memset(arr_char, 0x00, sizeof(arr_char));
                if (bytebuff_get_bytes(p_st_data, arr_char, 2) == FR_FAIL)
                    return FR_FAIL;

                i_ret = iconv_to_utf8(arr_char, 2, (char *)"UNICODEBIG", &p_iconved_buf, &ui_iconved_len);
                if (i_ret != 0)
                {
                    if (p_iconved_buf)
                        frfree(p_iconved_buf);
                }

                snprintf(arr_key, sizeof(arr_key), "%s.%d.%d", T3_EJB_FUNC_RETURN, u32_count, i+1);

                snprintf(arr_tmp, sizeof(arr_tmp), "%s", p_iconved_buf);
                frfree(p_iconved_buf);

                if (frreport_body_l7_add_str(p_st_body_data, arr_key, arr_tmp) == FR_FAIL)
                    return FR_FAIL;

                // 跳过成员名
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;

                break;
            case '[': //bytes todo
                if (bytebuff_peek_char(p_st_data, &u8_char) == FR_FAIL)
                    return FR_FAIL;

                if (u8_char == '\x75')
                {
                    bytebuff_skip(p_st_data, 5);

                    if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
                        return FR_FAIL;

                    if (u16_len != 0)
                    {
                        snprintf(arr_key, sizeof(arr_key), "%s.%d.%d", T3_EJB_FUNC_RETURN, u32_count, i+1);

                        p_data = (char *)frmalloc(u16_len);
                        if(p_data == NULL)
                            return FR_FAIL;

                        if(bytebuff_get_bytes(p_st_data, p_data, u16_len) == FR_FAIL)
                        {
                            frfree(p_data);
                            return FR_FAIL;
                        }

                        if (frreport_body_l7_add_bin(p_st_body_data, arr_key, p_data, u16_len) == FR_FAIL)
                        {
                            frfree(p_data);
                            return FR_FAIL;
                        }
                        frfree(p_data);
                    }
                }
                else
                {
                    snprintf(arr_key, sizeof(arr_key), "%s.%d.%d", T3_EJB_FUNC_RETURN, u32_count, i+1);

                    if (frreport_body_l7_add_bin(p_st_body_data, arr_key, NULL, 0) == FR_FAIL)
                        return FR_FAIL;
                }

                // 跳过成员名
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;

                bytebuff_skip(p_st_member, 1);
                // 跳过"B["
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;
                break;
            case 'L': //string
                if (bytebuff_peek_char(p_st_data, &u8_char) == FR_FAIL)
                    return FR_FAIL;
                //前段结束
                if (u8_char == '\x70')
                {
                    bytebuff_skip(p_st_data, 1);
                    if (bytebuff_peek_char(p_st_data, &u8_char) == FR_FAIL)
                        return FR_FAIL;
                }
                // String
                if (u8_char == '\x74')
                {
                    bytebuff_skip(p_st_data, 1);
                    if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
                        return FR_FAIL;

                    snprintf(arr_key, sizeof(arr_key), "%s.%d.%d", T3_EJB_FUNC_RETURN, u32_count, i+1);

                    p_data = (char *)frmalloc(u16_len + 1);
                    if (p_data == NULL)
                        return FR_FAIL;
                    memset(p_data, 0x00, u16_len + 1);

                    if (bytebuff_get_bytes(p_st_data, p_data, u16_len) == FR_FAIL)
                    {
                        frfree(p_data);
                        return FR_FAIL;
                    }

                    if (frreport_body_l7_add_str(p_st_body_data, arr_key, p_data) == FR_FAIL)
                    {
                        frfree(p_data);
                        return FR_FAIL;
                    }
                    frfree(p_data);
                }
                else
                {
                    snprintf(arr_key, sizeof(arr_key), "%s.%d.%d", T3_EJB_FUNC_RETURN, u32_count, i+1);
                    if (frreport_body_l7_add_str(p_st_body_data, arr_key, "") == FR_FAIL)
                        return FR_FAIL;
                }
                // 跳过成员名
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;

                bytebuff_skip(p_st_member, 1);// 't'
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;
                break;
            case 'Z': //boolean
                if (bytebuff_get_char(p_st_data, &u8_char) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d.%d", T3_EJB_FUNC_RETURN, u32_count, i+1);

                if (frreport_body_l7_add_int(p_st_body_data, arr_key, u8_char) == FR_FAIL)
                    return FR_FAIL;

                // 跳过成员名
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;
                break;
            case 'B': //byte
                if (bytebuff_get_char(p_st_data, &u8_char) == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s.%d.%d", T3_EJB_FUNC_RETURN, u32_count, i+1);

                if (frreport_body_l7_add_int(p_st_body_data, arr_key, u8_char) == FR_FAIL)
                    return FR_FAIL;

                // 跳过成员名
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;
                break;
            case 't': //string
                // 跳过成员名
                if (wls_skip_utf(p_st_member) == FR_FAIL)
                    return FR_FAIL;
                i--;
                break;
            default:
                return FR_FAIL;
        }
    }

    return FR_SUCC;
}

/*!
 * t3 ejb 返回内容array解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param *p_arg_str           (int                   参数说明的字符串)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
FR_STATIC int __t3_ejb_getarray(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data)
{
    Frbyte_Packet *p_st_member = NULL;
    char arr_key[64];
    char *p_type = NULL;
    char *p_data = NULL;
    uint32_t u32_count = 0;
    uint16_t u16_len = 0;
    uint16_t u16_count = 0;
    uint8_t u8_char = 0;
    uint8_t u8_char2 = 0;
    int i_class_count = 0;
    int i_pos = 0;
    int i_entry_idx = 0;
    int i_end_idx = 0;
    int i = 0;
    int i_ret = 0;

    if (p_st_data == NULL || p_st_body_data == NULL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 5);

    if (bytebuff_get_int(p_st_data, 4, &u32_count, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    i_pos = bytebuff_getPosition(p_st_data);

    // 找到weblogic.rjvm.ClassTableEntry
    if (bytebuff_memstr(p_st_data, 0, 0, WEBLOGIC_EJB_CLASSTABLEENTRY, strlen(WEBLOGIC_EJB_CLASSTABLEENTRY), &i_entry_idx) == FR_FAIL)
    {
        snprintf(arr_key, sizeof(arr_key), "%s.1.1", T3_EJB_FUNC_RETURN);
        /* binary数据(bytes)上报 */
        p_data = (char *)frmalloc(u32_count);
        if(p_data == NULL)
            return FR_FAIL;

        if(bytebuff_peek_bytes(p_st_data, p_data, u32_count) == FR_FAIL)
        {
            frfree(p_data);
            return FR_FAIL;
        }

        if (frreport_body_l7_add_bin(p_st_body_data, arr_key, p_data, u32_count) == FR_FAIL)
        {
            frfree(p_data);
            return FR_FAIL;
        }

        frfree(p_data);
        return FR_SUCC;
    }

    bytebuff_setPosition(p_st_data, i_entry_idx+strlen(WEBLOGIC_EJB_CLASSTABLEENTRY));
    bytebuff_skip(p_st_data, 14);
    if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    if (u16_len == 2)
    {
        p_type = (char *)frmalloc(u16_len + 1);
        if (p_type == NULL)
            return FR_FAIL;
        memset(p_type, 0x00, u16_len + 1);
        if (bytebuff_get_bytes(p_st_data, p_type, u16_len) == FR_FAIL)
        {
            frfree(p_type);
            return FR_FAIL;
        }
        if (strncmp(p_type, "[B", 2) == 0)
        {
            frfree(p_type);
            i_class_count = __t3_get_class_count(p_st_data);
            if (i_class_count == 0)
                return FR_FAIL;

            for (i = 1; i < i_class_count; i++)
            {
                if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, WEBLOGIC_EJB_CLASSTABLEENTRY, strlen(WEBLOGIC_EJB_CLASSTABLEENTRY), &i_entry_idx) == FR_FAIL)
                    break;
                bytebuff_setPosition(p_st_data, i_entry_idx+strlen(WEBLOGIC_EJB_CLASSTABLEENTRY));

                if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, "\x78\x70\x72", 3, &i_end_idx) == FR_FAIL)
                    return FR_FAIL;

                bytebuff_setPosition(p_st_data, i_end_idx+3);

                // class长度
                if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
                    return FR_FAIL;
            }
        }
    }

    bytebuff_skip(p_st_data, u16_len);
    bytebuff_skip(p_st_data, 9);

    // 成员个数
    if (bytebuff_get_short(p_st_data, 2, &u16_count, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    // 剩余的数据复制到另一个bytebuff
    p_st_member = __t3_ejb_bytebuff_copy(p_st_data);
    if (p_st_member == NULL)
        goto err;

    bytebuff_setPosition(p_st_data, i_pos);
    if (bytebuff_get_char(p_st_data, &u8_char) == FR_FAIL)
        goto err;

    if (u8_char == '\x73')
    {
        if (bytebuff_get_char(p_st_data, &u8_char2) == FR_FAIL)
            goto err;

        if (u8_char2 == '\x72')
            bytebuff_skip(p_st_data, 3);
        else if (u8_char2 == '\x71')
            bytebuff_skip(p_st_data, 4);
    }

    for (i = 0; i < (int)u32_count; i++)
    {
        i_ret = __t3_ejb_get_funcvalue(p_st_data, p_st_member, p_st_body_data, u16_count, i+1);
        if (i_ret == FR_FAIL)
            goto err;

        if (bytebuff_get_char(p_st_data, &u8_char) == FR_FAIL)
            goto err;

        if (u8_char == '\x73')
        {
            if (bytebuff_get_char(p_st_data, &u8_char2) == FR_FAIL)
                goto err;

            if (u8_char2 == '\x72')
                bytebuff_skip(p_st_data, 3);
            else if (u8_char2 == '\x71')
                bytebuff_skip(p_st_data, 4); // xx 7e + 2位长度
        }
        bytebuff_rewind(p_st_member);
    }

    bytebuff_free(&p_st_member);

    return FR_SUCC;

err:
    if (p_st_member)
        bytebuff_free(&p_st_member);

    return FR_FAIL;
}

/*!
 * t3 ejb 返回内容binary上报
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param *p_arg_str           (int                   参数说明的字符串)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
FR_STATIC int __t3_ejb_resp_report(Frbyte_Packet *p_st_data
                        , Frreport_body_data *p_st_body_data)
{
    char *p_data = NULL;
    char arr_key[64];
    int i_end = 0;
    int i_len = 0;

    if (p_st_data == NULL || p_st_body_data == NULL)
        return FR_FAIL;

    if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, "\x70", 1, &i_end) == FR_FAIL)
        return FR_FAIL;

    i_len = i_end - bytebuff_getPosition(p_st_data);
    p_data = (char *)frmalloc(i_len + 1);
    if (p_data == NULL)
        return FR_FAIL;

    if (bytebuff_get_bytes(p_st_data, p_data, i_len) == FR_FAIL)
    {
        frfree(p_data);
        return FR_FAIL;
    }

    snprintf(arr_key, sizeof(arr_key), "%s.1.1", T3_EJB_FUNC_RETURN);
    if (frreport_body_l7_add_bin(p_st_body_data, arr_key, p_data, i_len) == FR_FAIL)
    {
        frfree(p_data);
        return FR_FAIL;
    }

    frfree(p_data);

    return FR_SUCC;
}

/*!
 * t3 ejb 请求解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param *i_need_report       (int                   是否需要上报)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
int t3_ejb_analysis_req(L7session_t3_private *p_st_private
                      , Frbyte_Packet *p_st_data
                      , Frreport_body_data *p_st_body_data
                      , int *i_need_report)
{
    char *p_method_name = NULL;
    char *p_arg_str = NULL;
    uint16_t u16_len = 0;
    int i_arg_len = 0;
    int i_idx = 0;
    int i_ret = 0;

    if (p_st_data == NULL || p_st_body_data == NULL  || p_st_private == NULL)
        return FR_FAIL;

    *i_need_report = T3_NO;

    // WEBLOGIC_EJB_METHODDESC
    if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, WEBLOGIC_EJB_METHODDESC, strlen(WEBLOGIC_EJB_METHODDESC), &i_idx) == FR_FAIL)
        return FR_SUCC;

    bytebuff_setPosition(p_st_data, i_idx+strlen(WEBLOGIC_EJB_METHODDESC)+15);

    // 方法名长度
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    p_method_name = (char *)frmalloc(u16_len + 1);
    if (p_method_name == NULL)
        return FR_FAIL;

    memset(p_method_name, 0x00, u16_len + 1);

    i_ret = bytebuff_get_bytes(p_st_data, p_method_name, u16_len);
    if (i_ret == FR_FAIL)
    {
        frfree(p_method_name);
        return FR_FAIL;
    }

    // 从方法名中取参数类型
    p_arg_str = strchr(p_method_name, '(');
    if (p_arg_str == NULL)
    {
        frfree(p_method_name);
        return FR_FAIL;
    }

    *p_arg_str = '\0';
    // 方法名上报
    i_ret = frreport_body_l7_add_str(p_st_body_data, T3_EJB_FUNC, p_method_name);
    if (i_ret == FR_FAIL)
    {
        frfree(p_method_name);
        return FR_FAIL;
    }

    // 去前后括号
    p_arg_str++;
    i_arg_len = strlen(p_arg_str);
    p_arg_str[i_arg_len-1] = '\0';

    // 没有参数
    if (*p_arg_str == '\0')
    {
        *i_need_report = T3_YES;
        frfree(p_method_name);
        return FR_SUCC;
    }

    bytebuff_rewind(p_st_data);
    bytebuff_skip(p_st_data, 19+3);

    i_ret = __t3_ejb_getarg(p_st_private, p_st_data, p_st_body_data, p_arg_str);
    frfree(p_method_name);

    *i_need_report = T3_YES;

    return i_ret;
}

/*!
 * t3 ejb 响应解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param *i_need_report       (int                   是否需要上报)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
int t3_ejb_analysis_resp(L7session_t3_private *p_st_private
                  , Frbyte_Packet *p_st_data
                  , Frreport_body_data *p_st_body_data
                  , int *i_need_report)
{
    L7Session_t3 *p_st_session = NULL;
    char *p_data = NULL;
    char arr_key[64];
    uint8_t u8_char = 0;
    uint16_t u16_len = 0;
    int i_idx = 0;
    int i_ret = 0;

    if (p_st_data == NULL || p_st_body_data == NULL  || p_st_private == NULL
        || p_st_private->p_st_session == NULL)
        return FR_FAIL;

    *i_need_report = T3_NO;
    p_st_session = p_st_private->p_st_session;

    // ejb名
    if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, WEBLOGIC_EJB_BUSINESSOBJ, strlen(WEBLOGIC_EJB_BUSINESSOBJ), &i_idx) != FR_FAIL)
    {
        i_ret = __t3_ejb_getname(p_st_data, p_st_session);
        if (p_st_private->p_st_fragment->u32_left_len != 0)
        {
            bytebuff_set_skip(p_st_data, p_st_private->p_st_fragment->u32_left_len);
            return APM_L7_ANALYZE_TODO;
        }
        return i_ret;
    }

    if (bytebuff_peek_char(p_st_data, &u8_char) == FR_FAIL)
        return FR_FAIL;

    switch (u8_char)
    {
        case '\x74': //string
            bytebuff_skip(p_st_data, 1);

            if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;

            p_data = (char *)frmalloc(u16_len + 1);
            if (p_data == NULL)
                return FR_FAIL;
            memset(p_data, 0x00, u16_len + 1);

            if (bytebuff_get_bytes(p_st_data, p_data, u16_len) == FR_FAIL)
            {
                frfree(p_data);
                return FR_FAIL;
            }

            snprintf(arr_key, sizeof(arr_key), "%s.1.1", T3_EJB_FUNC_RETURN);
            if (frreport_body_l7_add_str(p_st_body_data, arr_key, p_data) == FR_FAIL)
            {
                frfree(p_data);
                return FR_FAIL;
            }
            frfree(p_data);
            break;
        case '\x75':
            i_ret = __t3_ejb_getarray(p_st_data, p_st_body_data);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        default:
            i_ret = __t3_ejb_resp_report(p_st_data, p_st_body_data);
            *i_need_report = T3_YES;
            return FR_SUCC;
    }

    *i_need_report = T3_YES;

    return i_ret;
}
